package com.hxgis.oc.product;

import com.hxgis.oc.config.OConfig;
import com.hxgis.oc.ncep.NcepTmp;
import com.hxgis.oc.ncep.NcepUV;
import com.hxgis.oc.ncep.base.NcepBase;
import com.hxgis.oc.product.base.ProductFactory;
import com.hxgis.oc.product.base.ProductFactoryManager;
import com.hxgis.oc.product.file.DownloadTask;
import com.hxgis.oc.product.file.FileProductManager;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;

@Slf4j
public class LiveProduct {
    private static FileProductManager fileProductManager;
    private final static HashSet<String> acceptMap = new HashSet<>();
    private final static Map<String, ReentrantLock> locks = new ConcurrentHashMap<>();

    private static void lockProducing(String key){
        ReentrantLock lk = locks.computeIfAbsent(key,l->new ReentrantLock(true));
        lk.lock();
    }

    private static void unlockProducing(String key){
        if(locks.containsKey(key)){
            locks.get(key).unlock();
            locks.remove(key);
        }
    }

    public static File getFile(String ds,long fid,String product){
        if(fileProductManager == null){
            Collections.addAll(acceptMap, OConfig.getConfig().getProductLive());
            fileProductManager = (FileProductManager) ProductFactoryManager.getFactory(FileProductManager.getFactoryName());
        }

        if(!acceptMap.contains(ds)){
            return null;
        }

        ProductFactoryManager.register(ds);

        DownloadTask task = null;
        File outputFile = null;

        String producingKey = ds + fid;

        if(ds.equals(NcepTmp.varName)){
            NcepBase request = new NcepTmp();
            outputFile = fileProductManager.getFile(ds,request.generateOutputFileName(fid));
            task = request.createATask(fid,outputFile);
        }
        else if(ds.equals(NcepUV.varName)){
            NcepBase request = new NcepUV();
            outputFile = fileProductManager.getFile(ds,request.generateOutputFileName(fid));
            task = request.createATask(fid,outputFile);
        }

        if(task == null || outputFile == null){
            return null;
        }

        lockProducing(producingKey);

        if(outputFile.exists()){
            log.debug("多次请求,由第一个请求的线程生产,我们谢谢这个线程 {}",outputFile.getName());
            return outputFile;
        }

        try {
            task.runSync();
            if(product != null){
                ProductFactory productFactory = ProductFactoryManager.getFactory(product);
                if(productFactory != null){
                    outputFile = productFactory.getFile(ds,fid);
                }
            }
        }catch (Exception ignored){}
        finally {
            unlockProducing(producingKey);
        }

        return outputFile;
    }
}
